--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Commit 7ffc072f87687063d943e4401c3a3f22b8f455f8
Parents : 926893f
Author : Mark Qvist <bc7291552be7a58f361522990465165c>
Signature : T66BB85Valid, signed by author
Date : 2026-07-16T13:43:30+02:00
Connection map rendering
Changes
5 files changed, 28 insertions(+), 8 deletions(-)
Diff
diff --git a/sbapp/mapview/clustered_marker_layer.py b/sbapp/mapview/clustered_marker_layer.py
index eb9f2a4e..212350ad 100644
--- a/sbapp/mapview/clustered_marker_layer.py
+++ b/sbapp/mapview/clustered_marker_layer.py
@@ -16,6 +16,7 @@ from kivy.properties import (
NumericProperty,
ObjectProperty,
StringProperty,
+ BooleanProperty,
)
from mapview.view import MapLayer, MapMarker, CustomMapMarker
@@ -43,14 +44,15 @@ Builder.load_string(
MDTelemetryIconButton:
app: root.app
- pos: [root.pos[0], root.pos[1]+dp(16)]
+ pos: [root.pos[0], root.pos[1]+dp(16)] if root.inspectable else [root.pos[0]+dp(7.5), root.pos[1]+dp(11)]
icon: root.icon
icon_color: root.icon_color
md_bg_color: root.md_bg_color
theme_icon_color: "Custom"
- icon_size: dp(32)
- _default_icon_pad: dp(16)
+ icon_size: dp(32) if root.inspectable else dp(22)
+ _default_icon_pad: dp(16) if root.inspectable else dp(11)
source_dest: root.source_dest
+ inspectable: root.inspectable
"""
)
@@ -291,6 +293,7 @@ class Marker:
self.widget.icon_color = self.icon_color
self.widget.md_bg_color = self.md_bg_color
self.widget.location_time = self.location_time
+ self.widget.inspectable = self.inspectable
@property
def app(self):
@@ -364,6 +367,18 @@ class Marker:
if not self.options: self.options = {}
self.options[k] = v
+ @property
+ def inspectable(self):
+ k = "inspectable"
+ if not self.options: return None
+ else: return self.options.get(k, None)
+
+ @inspectable.setter
+ def inspectable(self, v):
+ k = "inspectable"
+ if not self.options: self.options = {}
+ self.options[k] = v
+
def __repr__(self):
return f"<{self.cls} Proxy lat={self.lat} lon={self.lon}: {self.options}>"
@@ -511,7 +526,9 @@ class ClusterMapMarker(MapMarker):
if self.delegate and e: self.delegate.show_bbox(e[0], e[1], e[2], e[3])
class MDTelemetryIconButton(MDIconButton):
- def on_release(self, *args): self.app.map_display_telemetry(self)
+ def on_release(self, *args):
+ if self.inspectable: self.app.map_display_telemetry(self)
+ else: RNS.log(f"No inspectable data for {RNS.prettyhexrep(self.source_dest)}", RNS.LOG_DEBUG)
class TelemetryClusterMarker(CustomMapMarker):
source_dest = ObjectProperty(None)
@@ -520,6 +537,7 @@ class TelemetryClusterMarker(CustomMapMarker):
icon_color = ListProperty([1, 1, 1, 1])
md_bg_color = ListProperty([1, 1, 1, 1])
location_time = NumericProperty(0)
+ inspectable = BooleanProperty(True)
def __init__(self, **kwargs):
if "md_bg_color" in kwargs:
diff --git a/sbapp/mapview/icons/marker_dark.png b/sbapp/mapview/icons/marker_dark.png
index 50f93b5b..58c4fe8a 100644
Binary files a/sbapp/mapview/icons/marker_dark.png and b/sbapp/mapview/icons/marker_dark.png differ
diff --git a/sbapp/mapview/icons/marker_light.png b/sbapp/mapview/icons/marker_light.png
index 8570402e..2b84a437 100644
Binary files a/sbapp/mapview/icons/marker_light.png and b/sbapp/mapview/icons/marker_light.png differ
diff --git a/sbapp/sideband/cli/cmd_system.py b/sbapp/sideband/cli/cmd_system.py
index 8406168b..652b815b 100644
--- a/sbapp/sideband/cli/cmd_system.py
+++ b/sbapp/sideband/cli/cmd_system.py
@@ -31,9 +31,11 @@ def _cmd_raw(args, sideband, ctx):
try:
result = eval(expr)
- # result = exec(expr)
if result is not None: return repr(result)
else: return "None"
+ except SyntaxError:
+ exec(expr)
+ return None
except Exception as e: return f"Error: {e}"
def _cmd_log(args, sideband, ctx):
diff --git a/sbapp/ui/map.py b/sbapp/ui/map.py
index cf617fb9..8f12dd23 100644
--- a/sbapp/ui/map.py
+++ b/sbapp/ui/map.py
@@ -451,14 +451,14 @@ class Map():
RNS.log("Could not create map marker for "+RNS.prettyhexrep(source)+": "+str(e), RNS.LOG_ERROR)
return None
- def create_clustered_marker(self, source, telemetry, appearance):
+ def create_clustered_marker(self, source, telemetry, appearance, inspectable=True):
try:
l = telemetry["location"]; a_icon = appearance[0]
a_fg = appearance[1]; a_bg = appearance[2]
clustered_marker = self.clustered_layer.add_marker(l["longitude"], l["latitude"], cls=TelemetryClusterMarker,
options={"source_dest": source, "app": self.app,
"icon": a_icon, "icon_color": a_fg, "md_bg_color": a_bg,
- "location_time": l["last_update"]})
+ "location_time": l["last_update"], "inspectable": inspectable})
return clustered_marker
except Exception as e:
@@ -637,7 +637,7 @@ class Map():
if_appearance[2] = source_appearance[2]
plat = float(p["latitude"]); plon = float(p["longitude"]); palt = float(p["altitude"])
telemetry = {"location": {"latitude": plat, "longitude": plon, "altitude": palt, "last_update": time.time()}}
- marker = self.create_clustered_marker(p_hash, telemetry, if_appearance)
+ marker = self.create_clustered_marker(p_hash, telemetry, if_appearance, inspectable=False)
marker.parent = telemetry_source
if marker != None:
self.clustered_markers[p_hash] = marker
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────